package cn.bearspark.api.service.main.impl;

import cn.bearspark.api.controller.main.FileController;
import cn.bearspark.api.service.main.FileService;
import cn.bearspark.common.constant.GlobalConstant;
import cn.bearspark.common.parse.Pipeline;
import cn.bearspark.common.parse.host.HostParser;
import cn.bearspark.common.parse.host.HostPipeline;
import cn.bearspark.common.parse.host.HostTextContext;
import cn.bearspark.common.util.FileUtil;
import cn.bearspark.file.rpc.FileRpc;
import cn.bearspark.framework.web.starter.vo.ResponseVO;
import org.apache.dubbo.config.annotation.DubboReference;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.io.Resource;
import org.springframework.core.io.UrlResource;
import org.springframework.http.HttpHeaders;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.net.MalformedURLException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardCopyOption;
import java.util.UUID;

import static cn.bearspark.common.constant.GlobalConstant.BASE_DIR;

/**
 * @author f
 */
@Service
public class FileServiceImpl implements FileService {

    // TODO 之后需要考虑文件的压缩、分片上传功能

    private static final Logger LOGGER = LoggerFactory.getLogger(FileController.class);

    /**
     * 默认的 url 路径前缀
     */
    private static final String DEFAULT_URL_PREFIX = "http://<h>/bear-spark/file/download/";

    /**
     * 解析主机 ip 地址的管道
     */
    private final Pipeline<HostTextContext> hostPipeline = new HostPipeline()
            .add(new HostParser());

    @DubboReference(check = GlobalConstant.DUBBO_CHECK)
    private FileRpc fileRpc;

    @Override
    public ResponseVO<String> upload(MultipartFile file, Integer moduleCode) {
        // 如果 文件为空 或 文件没有名称，则返回错误响应
        String oriFilename = file.getOriginalFilename();
        if (file.isEmpty() || !StringUtils.hasLength(oriFilename)) {
            return ResponseVO.fail();
        }

        String extension = oriFilename.substring(oriFilename.lastIndexOf("."));
        String filename = UUID.randomUUID() + extension;
        Path filePath = Paths.get(BASE_DIR).resolve(filename).normalize();

        // 延迟删除图片
        if (FileUtil.isPhoto(extension)) {
            fileRpc.prepareDeletion(filename, moduleCode);
        }

        try {
            Files.copy(file.getInputStream(), filePath, StandardCopyOption.REPLACE_EXISTING);
            return ResponseVO.success(hostPipeline.unparse(hostPipeline.parse(DEFAULT_URL_PREFIX + filename)));
        } catch (IOException e) {
            LOGGER.error(e.getMessage(), e);
            return ResponseVO.fail();
        }
    }

    @Override
    public ResponseEntity<Resource> download(String filename) {
        try {
            Path filePath = Paths.get(BASE_DIR).resolve(filename).normalize();
            Resource resource = new UrlResource(filePath.toUri());

            if (!(resource.exists() || resource.isReadable())) {
                LOGGER.error("resource does not exist or is not readable");
            }

            return ResponseEntity.ok()
                    .header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=\"" + resource.getFilename() + "\"")
                    .body(resource);
        } catch (MalformedURLException e) {
            LOGGER.error(e.getMessage(), e);
        }
        return ResponseEntity.badRequest().build();
    }
}
